package cn.kk.filter;

import cn.kk.xss.XssHttpServletRequestWrapper;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * @Author: kk
 * @Date: 2023/3/5  16:08
 * @Version 1.0
 */
@Data
@Slf4j
@WebFilter(filterName = "XSSFilter", urlPatterns = "/*")
@Configuration
@ConfigurationProperties(prefix = "xss")
public class XssFilter implements Filter {

    private List<String> url;

    // 注解配置的是urlPatterns="/*"(过滤所有请求),所以这里对不需要过滤的静态资源url,作忽略处理(可以依照具体需求配置)
    private static final String[] exclusionsUrls = {".js", ".gif", ".jpg", ".png", ".css", ".ico",
            "/doc.html",
            "/webjars/**",
            "/swagger-resources",
            "/v2/api-docs"};

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String path = req.getServletPath();
        for (String str : url) {
            if (path.contains(str)) {
                chain.doFilter(request, response);
                return;
            }
        }
        // 处理请求，在XssHttpServletRequestWrapper里定义XSS漏洞预防代码
        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(req);
        chain.doFilter(xssRequest, response);
        // Cookie防护
        HttpServletResponse resp = (HttpServletResponse) response;
        // X-Frame-Options 保证自己的页面不会被嵌入到非同源的网页中
        resp.setHeader("x-frame-options", "SAMEORIGIN");
    }

    @Override
    public void init(FilterConfig filterConfig) {
        log.info("XSS预防策略加载完毕");
        url.addAll(Arrays.asList(exclusionsUrls));
    }

    @Override
    public void destroy() {

    }

}